<?php
/**
 * Parcl
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://parcl.com/license
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@parcl.com so we can send you a copy immediately.
 *
 * @category parcl
 * @package parcl-core
 * @copyright Copyright (c) 2006-2011 Mikael Knutsson (http://mikn.me)
 * @license http://parcl.com/license New BSD License
 */

if(PARCL_EXEC !== 1) {
    die('<h1>Incorrect Access</h1>You cannot access this file directly.<br/>' .
         'If you got this error message by clicking a link on the site,' .
         'please notify the webmaster as soon as possible.');
}

/**
 * TODO: Research about factory classes and see if this doCurrent class can be factored in runtime instead.
 */

class doCurrent {
    public $page;
    public $pageID;
}


/**
 * Purpose     : To carry system-global variables and objects without using globals.
 * Description : The Registry class is defined as a simpleton to make sure that
                 no duplicates are made by accident, it is possible to add, but
                 not remove or replace content. You can alter content by reference.
 * - Construct -
 * Input       : None.
 * Output      : Not applicable.
 * Description : It adds the standard variables to be present in the Registry
                 from the start.
 * Errors      : No error conditions are defined.
 * Assumptions : That the confparcl.php file contains a class called confParcl
                 and that that class contains parameters called pageSwitch and startPage.
 */

class Registry implements ISingleton {
    public $Current = null;
    private $data = null;
    private static $instance = null;

    public static function GetInstance() {
        if(is_null(self::$instance)) {
            self::$instance = new Registry();
        }
        return self::$instance;
    }

    private function __construct() {
        $this->data = new ArrayObject();
        $this->Current = new doCurrent();
        $scanModules = ScanModules::GetInstance();

        $this->Register('currentTime', time());
        $this->Register('modules', $scanModules->FindModules());
        $this->Register('ScanModules', $scanModules);
    }

    /**
     * __set
     * Output      : None
     * Description : Defined this function to make certain that you cannot set
                     variables in the registry class.
     * Errors      : Throws an error in case someone actually tries to set a
                     value to a member in the Registry.
     */

    public function __set($member, $value) {
        if($member == 'current') {
            $member = $value;
            return;
        }
        throw new GeneralException('Cannot set values in the registry class. ' .
                                "Tried setting member: $member to value: $value",
                                GeneralException::REGISTRY);
    }

    /**
     * __get
     * Output      : Returns the parcl settings object if asked for.
     * Description : This function exists to make it easier to access the config
                     information and to make sure that it cannot be alted and
                     transported to some place where it matters during runtime.
     * Errors      : Throws an error any time anyone tries to access any other
                     property than the defined 'conf' one.
     */

    public function __get($member) {
        if($member == 'conf') {
            return new confParcl();
        }
        if($member == 'current') {
            return $member;
        }
        throw new GeneralException('Tried to get a member from the registry that does '
                                 . 'not exist. Name: ' . $member, GeneralException::REGISTRY);
    }

    /**
     * Input       : $name: A unique name that you will later access the value of
                     the entry through.
                     $value: The value of the entry.
     * Output      : Boolean true if it succeeds.
     * Description : You add stuff to the registry with this function.
     * Errors      : If the entry already exists, a notice-level Exception is thrown.
     * Assumptions : That $name is a string.
     */

    public function Register($name, $value) {
        if(! $this->Exists($name)) {
            $this->data->offsetSet($name, $value);
            return true;
        }
        else {
            throw new GeneralException('Trying to add entry ' . $name . ' with value ' .
                                    $value . ' to the registry that already exists with value ' .
                                    $this->Get($name) . '.', GeneralException::REGISTRY_NOTICE);
        }
    }

    /**
     * Input       : $name: The unique name of a registry entry.
     * Output      : The contents of the registry entry carrying the name of $name.
     * Description : This function fetches stuff from the registry.
     * Errors      : Throws an error if the entry doesn't exists.
     * Assumptions : That $name is a string.
     */

    public function Get($name) {
        if($this->Exists($name)) {
            return $this->data->offsetGet($name);
        }
        else {
            throw new GeneralException('Trying to fetch entry ' . $name . ' in the registry
                                    that isn\'t set yet.', GeneralException::REGISTRY);
        }
    }

    /**
     * Input       : $name: The name of a registry entry.
     * Output      : Boolean true if the entry exists, boolean false if it doesn't.
     * Description : Checks if an entry exists in the registry.
     * Errors      : None.
     * Assumptions : That $name is a string.
     * Dev Notes   : Perhaps make this a private function since I can't see the
                     use of calling this from outside.
     */

    public function Exists($name) {
        return array_key_exists($name, $this->data);
    }

}